<?php
class PreProcessor
{
	public $defines;
	
	function __construct()
	{
		$this->defines = array();
	}
	
	public function parse($dataReader)
	{
		$str = '';
		while($dataReader->pos < $dataReader->size)
		{
			$val = $dataReader->data[$dataReader->pos];
			$size = $dataReader->size - $dataReader->pos;
			if($val == '"')
			{
				$str .= '"';
				$dataReader->pos++;
				$escape = false;
				while($dataReader->pos < $dataReader->size)
				{
					$val = $dataReader->data[$dataReader->pos];
					if($val == '"' && !$escape)
						break;
					else if($val == "\\" && !$escape)
						$escape = true;
					else $escape = false;
					$str .= $val;
					$dataReader->pos++;
				}
			}
			else if($val == '#')
			{
				$start = $dataReader->pos;
				$dataReader->pos++;
				$val = $this->readStr($dataReader);
				if($val == 'if')
				{
					$this->skipEspace($dataReader);
					$val = $this->readStr($dataReader);
					$defines = $this->defines;
					$ret = $this->parse($dataReader);
					$branch = array_key_exists($val, $defines);
					if($branch)
					{
						$str .= $ret;   
						$defines = $this->defines;
					}
					while($dataReader->pos < $dataReader->size)
					{                  
						$this->defines = $defines;
						$val = $dataReader->data[$dataReader->pos];
						if($val != '#')
						{
							echo 'erreur preprocesseur #if sans #endif';
							return '';
						}
						$dataReader->pos++; 
						$val = $this->readStr($dataReader);         
						if($val == 'else')
						{
							$ret = $this->parse($dataReader);
							if(!$branch)
							{
								$str .= $ret;      
								$defines = $this->defines;
							}
						}
						else if($val == 'elseif')
						{
							$val = $this->readStr($dataReader);
							$ret = $this->parse($dataReader);
							if(!$branch && array_key_exists($val))
							{      
								$str .= $ret;       
								$defines = $this->defines;
								$branch = true;
							}
						}
						else if($val == 'endif')
							break;
					}
				}
				else if($val == 'define')
				{
					$this->skipEspace($dataReader);
					$val1 = $this->readStr($dataReader);
					$this->skipEspace($dataReader);
					$this->defines[$val1] = '';
					while($dataReader->pos < $dataReader->size)
					{
						$val = $dataReader->data[$dataReader->pos];
						if($val == "\r" || $val == "\n")
							break;
						$this->defines[$val1] .= $val;
						$dataReader->pos++;
					}
				}
				else 
				{
					$dataReader->pos = $start;
					break;
				}
			}
			else if($val == '/' && $size >1 && $dataReader->data[$dataReader->pos+1] == '*')
			{
				$dataReader->pos += 2;
				while($dataReader->pos < $dataReader->size-1)
				{
					if($dataReader->data[$dataReader->pos] == '*' && $dataReader->data[$dataReader->pos+1] == '/')
						break;
					$dataReader->pos++;
				}
				$dataReader->pos++;
			}
			else if($val == '/' && $size >1 && $dataReader->data[$dataReader->pos+1] == '/')
			{
				$dataReader->pos += 2;
				while($dataReader->pos < $dataReader->size)
				{
					if($dataReader->data[$dataReader->pos] == "\n")
						break;
					$dataReader->pos++;
				}
			}
			else if(($val >= 'a' && $val <= 'z') || ($val >= 'A' && $val <= 'Z'))
			{
				$start = $dataReader->pos;
				$val = $this ->readStr($dataReader);
				if(array_key_exists($val, $this->defines))
				{
					echo $val." found !!";
					$dataReader->data = substr_replace($dataReader->data, $this->defines[$val], $start, $dataReader->pos-$start);
					$dataReader->size = strlen($dataReader->data);
					$dataReader->pos = $start-1;
				}
				else 
				{
					$str .= $val;
					continue;
				}
			}
			else $str .= $val;
			
			$dataReader->pos++;
		}
		return $str;
	}
	
	public function readStr(&$dataReader)
	{
		$str = '';
		while($dataReader->pos < $dataReader->size)
		{
			$val = $dataReader->data[$dataReader->pos];
			if(!(($val >= 'a' && $val <= 'z') || ($val >= 'A' && $val <= 'Z') || ($val >= '0' && $val <= '9')))
				break;
			$str .= $val;
			$dataReader->pos++;
		}
		return $str;
	}    
	
	public function skipEspace(&$dataReader)
	{
		while($dataReader->pos < $dataReader->size)
		{
			$val = $dataReader->data[$dataReader->pos];
			if($val != ' ' && $val != "\t")
				break;
			$dataReader->pos++;
		}
	}
}
?>
